package Distributive;

import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;

public class synchronizedBuffer implements IBuffer {

	private static final int MAX_BUFFER_SIZE = 2;

	private Lock bufferLock;
	private Condition canWrite;
	private Condition canRead;

	private ArrayList<String> bufferContents = new ArrayList<String>();

	/**
	 * constructor for the synchronizedBuffer
	 */
	public synchronizedBuffer() {
		bufferLock = new ReentrantLock();
		canWrite = bufferLock.newCondition();
		canRead = bufferLock.newCondition();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see Distributive.IBuffer#setValue(java.lang.String)
	 */
	public void setValue(String value) {
		bufferLock.lock();

		try {
			while (this.bufferContents.size() == MAX_BUFFER_SIZE) {
				System.out.println("Producer tries to write.");
				System.out.println("Buffer full. Producer waits.");
				canWrite.await();
			}
			bufferContents.add(value);

			canRead.signal();
		} catch (InterruptedException ie) {
			ie.printStackTrace();
		} finally {
			bufferLock.unlock();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see Distributive.IBuffer#getValue()
	 */
	public String getValue() {
		String valueFromBuffer = "";
		bufferLock.lock();
		try {
			while (this.bufferContents.isEmpty()) {
				System.out.println("Consumer tries to get value.");
				System.out.println("Buffer empty. Consumer waits.");
				canRead.await();
			}
			valueFromBuffer = this.bufferContents.remove(0);
			canWrite.signal();
		} catch (InterruptedException exception) {
			exception.printStackTrace();
		} finally {
			bufferLock.unlock();
		}

		return valueFromBuffer;
	}

}
